package cn.tac.test.base.reference;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author tac
 * @since 20/10/2018
 */
public class WeakRef {
    /**
     * VM Options: -Xms20m -Xmx20m
     */
    public static void main(String[] args) throws InterruptedException {
        List<WeakReference<Foo>> ls = new ArrayList<>();
        ls.add(new WeakReference<>(new Foo("foo1")));
        Foo foo = new Foo("foo2");
        WeakReference<Foo> weak1 = new WeakReference<>(foo);
        System.gc();    // gc后马上回收


        HashMap<String, WeakRefWithKey<Foo>> map = new HashMap<>();
        ReferenceQueue<Foo> queue = new ReferenceQueue<>();
        map.put("f1", new WeakRefWithKey<>("f1", new Foo("f1"), queue));
        map.put("f2", new WeakRefWithKey<>("f2", new Foo("f2"), queue));
        System.out.println(map.keySet());

        System.gc();
        WeakRefWithKey<? extends Foo> ref = (WeakRefWithKey<? extends Foo>) queue.remove();
        while (ref != null) {
            map.remove(ref.getKey());
            ref = (WeakRefWithKey<? extends Foo>) queue.poll();
        }
        System.out.println(map.keySet());
    }

    private static class Foo {
        private String name;

        public String getName() {
            return name;
        }

        public Foo(String name) {
            this.name = name;
        }

        @Override
        protected void finalize() throws Throwable {
            System.out.println("finalizing: " + name);
        }
    }

    private static class WeakRefWithKey<T> extends WeakReference<T> {
        private String key;

        public String getKey() {
            return key;
        }

        public WeakRefWithKey(String key, T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
            this.key = key;
        }
    }
}
